package joney.main.views;

import java.util.Date;
import java.util.Hashtable;

import joney.main.action.AccountActions;
import joney.main.action.IAccountsChanged;
import joney.main.action.ITransactionOccured;
import joney.main.utils.JoneyUtil;
import joney.main.views.table.ExpenseContentProvider;
import joney.main.views.table.ExpenseLabelProvider;
import joney.main.views.table.ExpenseList;
import joney.model.Account;
import joney.model.DataModel;
import joney.model.Expense;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.part.ViewPart;


/**
 * Main Accounts view
 * @author Sean McGrail
 *
 */
public class AccountsView extends ViewPart implements ITransactionOccured, IAccountsChanged{

	public static String ID= "joney.accountsview";
	
	private TabFolder tabFolder;
	private Combo comboTypes;
	
	//AccountName, list of expenses
	private Hashtable<String, ExpenseList> expenseLists = 
		new Hashtable<String, ExpenseList>();
	
	//main layout
	public void createPartControl(Composite parent) {
		
		//listener for transaction events
		DataModel.addTransactionListener(this);
		DataModel.addAccountsListener(this);
		
		//split between input and table
		SashForm mainSplit = new SashForm(parent, SWT.VERTICAL);
		mainSplit.SASH_WIDTH = 10;
		
		Composite topAreaSplit = new Composite(mainSplit, SWT.NONE);
		topAreaSplit.setBackground(JoneyUtil.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		
		//create main parts
		createInputArea(topAreaSplit);
		createTabbedAccounts(mainSplit);
		
		mainSplit.setWeights(new int[]{1, 3});
		
	//	initializeToolBar();
	}

	private void initializeToolBar() {
		
		IToolBarManager toolbarManager = getViewSite().getActionBars()
		.getToolBarManager();
		
		toolbarManager.add(new AccountActions.NewAccount(this.getSite().getWorkbenchWindow()));
		toolbarManager.add(new AccountActions.DeleteAccount(this.getSite().getWorkbenchWindow()));
		toolbarManager.add(new AccountActions.TransferAmount(this.getSite().getWorkbenchWindow()));
	} 
	
	/**
	 * Create popup menu for expense list
	 * @param names
	 */
	private void createPopupMenuName(final Text names)
	{	
		final Menu menu = new Menu (names.getShell(), SWT.POP_UP);

		
		
		menu.addListener (SWT.Show, new Listener () {
			public void handleEvent (Event event) {
				
				Menu currentMenu = menu;
				int subMenuCount = 40;
				int added = 0;
				
				String type = comboTypes.getText();
				
				//handle adding choices to a cascading menu
				if(!type.isEmpty()){
					for (String s: DataModel.getListOfNamesFromType(type)) {
						
						//if count has been reached create a new submenu
						if(added == subMenuCount)
						{
							MenuItem arrow = new MenuItem (currentMenu, SWT.CASCADE);
							currentMenu = new Menu(currentMenu);
							arrow.setMenu(currentMenu);
							
							added= 0;
								
						}
						
						MenuItem menuItem=null;
						
						
						menuItem = new MenuItem (currentMenu, SWT.PUSH);
						
						menuItem.setText (s);
						menuItem.addSelectionListener(new SelectionAdapter()
						{
							public void widgetSelected(SelectionEvent e) {
								names.setText(((MenuItem)e.getSource()).getText());
							}
						});
						added++;
					}
				}

				//delete all items and create a new menu
				createPopupMenuName(names);
			}
		});

		
		names.setMenu(menu);
	}
	
	//Create a popup menu for the table and table items
	private void createPopupMenuTable(final Table t, TableViewer tv)
	{
		final MenuManager mgr = new MenuManager();
		 
		mgr.add(new Action("Removed Selected")
		{
			public void run() {
				for(TableItem ti: t.getSelection())
				{
					Expense exp = (Expense)ti.getData();
					DataModel.fireExpenseRemoved(exp);
					expenseLists.get(tabFolder.getSelection()[0].getText()).removeExpense(exp);
				}
			}
		});
		
		
		
		mgr.add(new Action("Show all Name expense like this")
		{
			public void run() {
				IWorkbenchPage page = getViewSite().getWorkbenchWindow().getActivePage();
				for(TableItem ti: t.getSelection())
				{
					Expense e = (Expense)ti.getData();
					try {
						if(page == null){return;}
						String id = ExpenseTypeList.ID;
						String secId = String.valueOf(ExpenseTypeList.viewsOpen++);
						ExpenseTypeList er = (ExpenseTypeList)page.showView(id,secId, IWorkbenchPage.VIEW_ACTIVATE);
						er.loadTableNames(e.getName());
					} catch (PartInitException e1) {
						e1.printStackTrace();
					}
					
					//maybe more views?
					return;
				}
			}
		});
		
		mgr.add(new Action("Show all Type expense like this")
		{
			public void run() {
				IWorkbenchPage page = getViewSite().getWorkbenchWindow().getActivePage();
				for(TableItem ti: t.getSelection())
				{
					Expense e = (Expense)ti.getData();
					try {
						if(page == null){return;}
						String id = ExpenseTypeList.ID;
						String secId = String.valueOf(ExpenseTypeList.viewsOpen++);
						ExpenseTypeList er = (ExpenseTypeList)page.showView(id,secId, IWorkbenchPage.VIEW_ACTIVATE);
						er.loadTableType(e.getType());
					} catch (PartInitException e1) {
						e1.printStackTrace();
					}
					
					//maybe more views?
					return;
				}
			}
		});
		
		
//		mgr.addMenuListener(new IMenuListener()
//		{
//			public void menuAboutToShow(IMenuManager manager) {
//				
//			}
//		});
		
		tv.getControl().setMenu(mgr.createContextMenu(tv.getControl()));
		

	}
	
	
	private void createInputArea(Composite parent)
	{

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		
		parent.setLayout(layout);
		parent.setLayoutData(new GridData(SWT.FILL,SWT.FILL, true, true));
		
		//form left side
		
		FormToolkit toolkit = new FormToolkit(parent.getDisplay());
		Form form = toolkit.createForm(parent);
		form.setText("Expense Input");
		
		form.getBody().setLayout(layout);
		
		toolkit.createLabel(form.getBody(), "Name:");
		final Text name = toolkit.createText(form.getBody(), "");
		GridData gd = new GridData(GridData.BEGINNING);
		gd.widthHint = 200;
		name.setLayoutData(gd);
		createPopupMenuName(name);
		
		toolkit.createLabel(form.getBody(), "Type:");		
		final Combo type= new Combo(form.getBody(),SWT.FLAT | SWT.DROP_DOWN);
		comboTypes = type;
		comboTypes.setVisibleItemCount(20);
		
		toolkit.adapt(type);
		toolkit.paintBordersFor(form.getBody());
		gd = new GridData(GridData.BEGINNING);
		gd.widthHint = 185;
		type.setLayoutData(gd);
		
		
		toolkit.createLabel(form.getBody(), "Amount:");
		final Text amount = toolkit.createText(form.getBody(), "");
		gd = new GridData(GridData.BEGINNING);
		gd.widthHint = 200;
		amount.setLayoutData(gd);
		amount.addListener(SWT.Verify, new Listener() { //add numeric only
			           public void handleEvent(Event e) {
			              String string = e.text;
			              char[] chars = new char[string.length()];
			              string.getChars(0, chars.length, chars, 0);
			              for (int i = 0; i < chars.length; i++) {
			                if (!('0' <= chars[i] && chars[i] <= '9') && chars[i] != '.') {
			                  e.doit = false;
			                return;
			               }
			              }
			            }
		         });
		
		
		
//		Section noteSec = toolkit.createSection(form.getBody(), 
//				  Section.DESCRIPTION|Section.TITLE_BAR);
//
//		noteSec.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//		noteSec.setText("Note");
//	
//		Composite sectionClient = toolkit.createComposite(noteSec);
//		sectionClient.setLayout(new GridLayout());
//		
//		toolkit.createTree(sectionClient, SWT.MULTI);
//		noteSec.setClient(sectionClient);
		
		
		//checkbox for deposit/withdrawl
		final Button deposit = toolkit.createButton(form.getBody(), "Deposit", SWT.CHECK);
		

		//add a expense 
		Button add = toolkit.createButton(form.getBody(), "Add Expense", SWT.PUSH);
		add.addSelectionListener(new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent e) {
				
				if(!type.getText().isEmpty() && !amount.getText().isEmpty() && !type.getText().isEmpty())
				{
					DataModel.addExpenseTypeToList(type.getText());
					
					DataModel.fireExpenseAdded(new Expense(new Date().getTime(), 
							type.getText().toUpperCase().charAt(0) + type.getText().substring(1).toLowerCase(),
							name.getText(), "", 
							(deposit.getSelection()?1:-1)*Double.valueOf(amount.getText()).doubleValue()));
					
					name.setText("");
					amount.setText("");
				}
			}
			
		});
	
		//add return key listener to the amount text
		//add a expense
		 amount.addListener(SWT.DefaultSelection, new Listener() {
		      public void handleEvent(Event e) {
		    	  if(!type.getText().isEmpty() && !amount.getText().isEmpty() && !type.getText().isEmpty())
					{
						DataModel.addExpenseTypeToList(type.getText());
						
						DataModel.fireExpenseAdded(new Expense(new Date().getTime(), 
								type.getText().toUpperCase().charAt(0) + type.getText().substring(1).toLowerCase(),
								name.getText(), "", 
								(deposit.getSelection()?1:-1)*Double.valueOf(amount.getText()).doubleValue()));
						
						name.setText("");
						amount.setText("");
					}
		      }
		    });
		
		
		Form formRight = toolkit.createForm(parent);
		layout = new GridLayout();
		layout.numColumns = 1;
		formRight.getBody().setLayout(layout);
		
		Button syncDevice = toolkit.createButton(formRight.getBody(), "Sync Device", SWT.PUSH);
		syncDevice.addSelectionListener(new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent e) {
				try {
					getViewSite().getWorkbenchWindow()
					.getActivePage().showView(DeviceSyncView.ID);
				} catch (PartInitException e1) {
					e1.printStackTrace();
				}
			}
			
		});
//		

		//toolkit.createTable(formRight.getBody(), SWT.VIRTUAL | SWT.BORDER);
	}
	
	
	
	/**
	 * Create a accoutn table and hook all listeners up to it
	 * @param a
	 */
	private void setupAccountTable(Account a)
	{
		TabItem item = new TabItem (tabFolder, SWT.NULL);
		item.setText(a.getName());
		Table t = createTable(tabFolder);	
		t.setFont(new Font(JoneyUtil.getDisplay(), "Courier New", 12, SWT.NORMAL));
	
		TableViewer tv = createTableViewer(t);
		
		//set to tabbed
		item.setControl(t);
		
		//attach popup menu
		createPopupMenuTable(t, tv);
		
		
		//add data
		ExpenseList elist = new ExpenseList(a);
		
		//set providers
		tv.setLabelProvider(new ExpenseLabelProvider(elist));
		tv.setContentProvider(new ExpenseContentProvider(tv, elist));
		
		expenseLists.put(a.getName(), elist);
		tv.setInput(elist);
		
		//set focus
		if(t.getItemCount() >0)
		t.setSelection(t.getItemCount()-1);
		
		//set stripes
		int i=0;
		for(TableItem ti: tv.getTable().getItems()){
		
		//draw stripes
		if(i++ %2 !=0){
			ti.setBackground(new Color(JoneyUtil.getDisplay(),238,233,233));
			//ti.setForeground(JoneyUtil.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		}
		else{
			
			ti.setBackground(JoneyUtil.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		}
		}
	}
	
	
	/**
	 * Create the tabs and copy in the intial data
	 * @param parent
	 * @param accounts
	 */
	private void createTabbedAccounts(Composite parent)
	{
		if(parent != null)
		tabFolder = new TabFolder (parent, SWT.NONE);
		
		//add data and tabbeds to all accounts
		for(Account a: DataModel.accounts)
		{
			for(Expense e: a.getExpenses())
				DataModel.addExpenseTypeToList(e.getType());
			
			setupAccountTable(a);
		}
		
		//set tab size
		if(parent != null)
		tabFolder.setSize (400, 200);
		
		//update the combo box
		for(String t: DataModel.getExpenseTypes())
			comboTypes.add(t);
	}
	
	// Create the Table and TableColumns 
	private Table createTable(Composite parent) {
		int style = SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
				| SWT.FULL_SELECTION | SWT.HIDE_SELECTION;

	//	final int NUMBER_COLUMNS = 4;

		Table table = new Table(parent, style);

		GridData gridData = new GridData(GridData.FILL_BOTH);
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalSpan = 3;
		table.setLayoutData(gridData);

		table.setLinesVisible(true);
		table.setHeaderVisible(true);

		int colNum=0;
		
		TableColumn column = new TableColumn(table, SWT.LEFT, colNum++);
		column.setText(ExpenseLabelProvider.DATE);
		column.setWidth(180);
		// Add listener to column so tasks are sorted by description when
		// clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.DESCRIPTION));
			}
		});
		
		
		column = new TableColumn(table, SWT.LEFT, colNum++);
		column.setText(ExpenseLabelProvider.NAME);
		column.setWidth(200);
		// Add listener to column so tasks are sorted by description when
		// clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.DESCRIPTION));
			}
		});

		column = new TableColumn(table, SWT.LEFT, colNum++);
		column.setText(ExpenseLabelProvider.TYPE);
		column.setWidth(150);
		// Add listener to column so tasks are sorted by owner when clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.OWNER));
			}
		});

		column = new TableColumn(table, SWT.CENTER, colNum++);
		column.setText(ExpenseLabelProvider.AMOUNT_DEPOSIT);
		column.setWidth(130);
		// Add listener to column so tasks are sorted by percent when clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.PERCENT_COMPLETE));
			}
		});
		
		column = new TableColumn(table, SWT.CENTER, colNum++);
		column.setText(ExpenseLabelProvider.AMOUNT_WITHDRAWL);
		column.setWidth(130);
		// Add listener to column so tasks are sorted by percent when clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.PERCENT_COMPLETE));
			}
		});
		
		column = new TableColumn(table, SWT.RIGHT, colNum++);
		column.setText(ExpenseLabelProvider.TOTAL_AMOUNT);
		column.setWidth(150);
		// Add listener to column so tasks are sorted by percent when clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.PERCENT_COMPLETE));
			}
		});
		
		column = new TableColumn(table, SWT.RIGHT, colNum++);
		column.setText(ExpenseLabelProvider.NOTE);
		column.setWidth(150);
		// Add listener to column so tasks are sorted by percent when clicked
		column.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent e) {
				//tableViewer.setSorter(new ExampleTaskSorter(
				//		ExampleTaskSorter.PERCENT_COMPLETE));
			}
		});
		
		return table;
	}
	
	private TableViewer createTableViewer(Table table) {

		TableViewer tableViewer = new TableViewer(table);
		tableViewer.setUseHashlookup(true);
		
		tableViewer.setColumnProperties(ExpenseLabelProvider.columnNames);

		// Assign the cell editors to the viewer 
	//tableViewer.setCellEditors(editors);
		// Set the cell modifier for the viewer
	//	tableViewer.setCellModifier(new ExampleCellModifier(this));
		// Set the default sorter for the viewer 
	//	tableViewer.setSorter(new ExampleTaskSorter(ExampleTaskSorter.DESCRIPTION));
		
		
		return tableViewer;
	}

	
	public String getCurrentWorkingAccountName()
	{
		return tabFolder.getSelection()[0].getText();
	}
	
	
	
	public void setFocus() {
		tabFolder.setFocus();
	}


	public void expenseAdded(Expense e, String a) {
		
		//add to a specific account if specified
		if(a != null)
		{
			expenseLists.get(a).addExpense(e);
		}
		else {
			//add to the currently slected tab
			expenseLists.get(tabFolder.getSelection()[0].getText()).addExpense(e);
			
			//set focus
			Table tv = ((Table)tabFolder.getSelection()[0].getControl());
			tv.setSelection(tv.getItemCount()-1);
		}
		
		//update the combo box
		comboTypes.removeAll();
		for(String t: DataModel.getExpenseTypes())
			comboTypes.add(t);
	}


	public void expenseRemoved(Expense e, String accountNameString) {
	}



	public void accountAdded(Account a) {
		setupAccountTable(a);
	}


	public void accountRemoved(Account a) {
		
	}


	public void expensesUpdated() {
		
		//remove all current tab items
		for(TabItem ti: tabFolder.getItems())
		{
			ti.dispose();
		}
		
		createTabbedAccounts(null);
	}

	public void transferOccured(String fromAccount, String toAccount,
			Expense from, Expense to) {
		
	}


}
